package com.sunmouse.toollib.widget;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.sunmouse.toollib.R;
import com.sunmouse.toollib.utils.ListUtils;
import com.sunmouse.toollib.utils.LogUtils;

import java.util.ArrayList;

/**
 * Created by Kvin on 2017/2/5.
 */
public class ChoiceLayout extends ViewGroup {

    public static final String TAG = ChoiceLayout.class.getSimpleName();
    private TextView tv;
    private final int TYPE_TITLE = 1;
    private int marginLeft = 20;
    private final int marginTop = 20;
    private final Rect childRect = new Rect();
    private DisplayMetrics mMetrics;
    private int lineNum;

    private Mode mMode;

    private OnChoiceClickListener mOnChoiceClickListener;


    //attr
    private int verSpace;
    private int horSpace;
    private float txtSize;
    private int choiceTheme;
    private ArrayList<String> mData;
    private Drawable mBackground;
    private ColorStateList mTextColor;
    private int remainWidth;

    public ChoiceLayout(Context context) {
        super(context);
    }

    public ChoiceLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        initAttr(context, attrs);
    }

    /**
     * init attr
     */
    private void initAttr(Context context, AttributeSet attrs) {

        float density = getResources().getDisplayMetrics().density;
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ChoiceLayout);
        this.verSpace = typedArray.getDimensionPixelSize(R.styleable.ChoiceLayout_clVerSpace, (int) (10*density));
        this.horSpace = typedArray.getDimensionPixelSize(R.styleable.ChoiceLayout_clHorSpace, (int) (5*density));
        this.txtSize = typedArray.getDimension(R.styleable.ChoiceLayout_clTxtSize, 10*density);
        this.choiceTheme = typedArray.getInt(R.styleable.ChoiceLayout_clChoiceTheme, Theme.RED.value);
        this.mTextColor = typedArray.getColorStateList(R.styleable.ChoiceLayout_clTxtColor);
        typedArray.recycle();
        this.mBackground = getBackground();

        this.mMode = Mode.LEFT;

    }

    public ChoiceLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public ChoiceLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    /**
     * add children and init
     */
    public void addData(ArrayList<String> data) {
        if (ListUtils.isEmpty(data)) return;
        this.mData = data;
        for (String item : data) {
            tv = new TextView(getContext());
            setTheme(choiceTheme, tv);
            tv.setText(item);
            tv.setGravity(Gravity.CENTER);
            tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, txtSize);
            addView(tv);
        }
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        LogUtils.v(TAG, "---w=" + w);
        this.remainWidth = w - getPaddingLeft() - getPaddingRight();
    }

    /**
     *
     */
    public void notifyDataChanged() {
//        LogUtils.v("-----------size=" + mData.size());
        this.postInvalidate();
        this.requestLayout();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//        LogUtils.v(TAG, "---------onMeasure");
        measureChildren(widthMeasureSpec, heightMeasureSpec);//don`t forget
        int minRequiredHeight = calculatedHeight();
        setMeasuredDimension(widthMeasureSpec, minRequiredHeight);//set last child`s bottom as total height
//        int expandSpec = MeasureSpec.makeMeasureSpec(
//                Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
//
//        super.onMeasure(widthMeasureSpec, expandSpec);
    }

    /**
     * calculate max height
     *
     * @return
     */
    private int calculatedHeight() {
        int childCount = getChildCount();
        if (remainWidth == 0 || childCount == 0) return 0;
        int totalWidth = 0;
        for (int i = 0; i < childCount; i++) {
            totalWidth += getChildAt(i).getMeasuredWidth() + horSpace;
        }
        int lines = (totalWidth - horSpace) / remainWidth + 1;
        int validHeight = getChildAt(0).getMeasuredHeight() * (lines+1) + verSpace * (lines+1);
        return validHeight;
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
//        LogUtils.v(TAG, "---------onLayout");
        View child = null;
        boolean is = changed;
        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            child = getChildAt(i);
            child.setTag(i);
            child.setOnClickListener(mOnClickListener);
            if (i == 0) {
                calculateMarginLeft(i);
                childRect.left = marginLeft;
                childRect.top = marginTop;
                childRect.right = marginLeft + child.getMeasuredWidth();
                childRect.bottom = marginTop + child.getMeasuredHeight();

            } else if (childRect.right + horSpace + child.getMeasuredWidth() <= getWidth()) {
                //layout right
                childRect.left = childRect.right + horSpace;
                childRect.right = childRect.left + child.getMeasuredWidth();
                childRect.bottom = childRect.top + child.getMeasuredHeight();
            } else {
                //line feed
                calculateMarginLeft(i);
                childRect.left = marginLeft;
                childRect.top = childRect.bottom + verSpace;
                childRect.right = marginLeft + child.getMeasuredWidth();
                childRect.bottom = childRect.top + child.getMeasuredHeight();
                lineNum++;
            }
//            chooseTheme(lineNum / 2);
//            setTheme(choiceTheme, (TextView) child);
            //layout child
            child.layout(childRect.left, childRect.top, childRect.right, childRect.bottom);
        }
    }

    /**
     * choose a direct theme
     *
     * @param index
     */
    private void chooseTheme(int index) {
        choiceTheme = index;
    }

    /**
     * @return a random num (<=3)
     */
    private int setTheme() {
        int ran = (int) (Math.random() * 10 / 3);
        return ran;
    }


    /**
     * calculate marginLeft
     *
     * @param position
     */
    private void calculateMarginLeft(int position) {
        if (mMode == Mode.LEFT) {
            marginLeft = getPaddingLeft();
            return;
        }
        int i = 0;
        int count = getChildCount();
        int totalW = getTotalWidth(position, i);
        while (totalW <= getWidth()) {
            i++;
            if (i >= count - position) break;
            totalW = getTotalWidth(position, i + 1);
        }
        marginLeft = (getWidth() - getTotalWidth(position, i)) / 2;
    }

    /**
     * measure child total w
     *
     * @param position
     * @param n
     * @return
     */
    private int getTotalWidth(int position, int n) {
        int w = getChildAt(position).getMeasuredWidth();
        for (int i = 1; i < n; i++) {
            w += horSpace + getChildAt(position + i).getMeasuredWidth();
        }
        return w;
    }


    /**
     * title layout params
     */
    public LayoutParams getTitleLayoutParams() {
        LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
        return params;
    }

    /**
     * choice layout params
     */
    public LayoutParams getChoiceLayoutParams() {
        LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        return params;
    }

    /**
     * child view click
     */
    private OnClickListener mOnClickListener = new OnClickListener() {
        @Override
        public void onClick(View view) {
            if (mOnChoiceClickListener != null)
                mOnChoiceClickListener.onChoiceClick(view, (Integer) view.getTag());
        }
    };

    /**
     * set on item click listener
     */

    public void setOnChoiceClickListener(OnChoiceClickListener mOnChoiceClickListener) {
        this.mOnChoiceClickListener = mOnChoiceClickListener;
    }

    /**
     * set theme for textViews
     * you can define by yourself
     */
    private void setTheme(int theme, TextView tv) {
        switch (theme) {
            case 0:
                tv.setBackgroundResource(R.drawable.choice_red_bg);
                tv.setTextColor(getResources().getColor(R.color.choice_red_bg));
                break;
            case 1:
                tv.setBackgroundResource(R.drawable.choice_yellow_bg);
                tv.setTextColor(getResources().getColor(R.color.choice_yellow_bg));
                break;
            case 2:
                tv.setBackgroundResource(R.drawable.choice_green_bg);
                tv.setTextColor(getResources().getColor(R.color.choice_green_bg));
                break;
            case 3:
                tv.setBackgroundResource(R.drawable.choice_blue_bg);
                tv.setTextColor(getResources().getColor(R.color.choice_blue_bg));
                break;
        }

    }

    /**
     * set theme
     *
     * @param theme
     * @param tv
     */
    public void setTheme(Theme theme, TextView tv) {
        setTheme(theme.value, tv);
    }

    /**
     * set mode
     */
    public void setMode(Mode mode) {
        this.mMode = mode;
        postInvalidate();
    }

    public enum Theme {
        RED(0), YELLOW(1), GREEN(2), BLUE(3);

        private int value;

        Theme(int value) {
            this.value = value;
        }
    }

    /**
     * mode
     */
    public enum Mode {
        LEFT(0), CENTER(1);

        private int value;

        Mode(int value) {
            this.value = value;
        }
    }

    /**
     * choice click listener
     */
    public interface OnChoiceClickListener {
        void onChoiceClick(View view, int position);
    }
}
